<?php
class mcz_Tune extends mcz_Object
{
    protected $fields = array(
        'id'      => array('cast' => 'integer'),
        'path'    => array('cast' => 'string',
                           'notblank' => true,
                           'unique' => true,
                           'validators' => array('isFile')),
        'file_modified' => array('cast' => 'integer'),
        'artist'  => array('cast' => 'string',
                           'notblank' => true),
        'title'   => array('cast' => 'string',
                           'notblank' => true),
        'album'   => array('cast' => 'string'),
        'year'    => array('cast' => 'integer'),
        'track'   => array('cast' => 'integer'),
        'genre'   => array('cast' => 'string'),
        'comment' => array('cast' => 'string'),
        'time'    => array('cast' => 'integer')
    );

    protected function preSave()
    {
        $this->file_modified = filemtime(mcz_TUNES_DIR . $this->path);
    }

    protected function postSave()
    {
        $this->indexDatas();
    }

    protected function isFileValidator($file)
    {
        return is_file(mcz_TUNES_DIR . $file);
    }

    public function indexDatas()
    {
        mcz_TuneIndex::deleteFromTuneId($this->id);
        $indexedFields = array('artist', 'title', 'album', 'genre', 'comment');
        foreach($indexedFields as $field)
        {
            $words = mcz_Analyzer::analyze($this->$field);
            foreach($words as $word)
            {
                $idx = new mcz_TuneIndex(array(
                                               'key'     => $word,
                                               'field'   => $field,
                                               'tune_id' => $this->id
                                               ));
                $idx->save();
            }
        }
    }

    public static function findByIds(array $ids)
    {
        return self::hydrate(get_class(),
                             self::dbh()->fetch('* from mcz_Tune where id in(' . implode(',', $ids) . ')'));
    }

    public static function findAll()
    {
        return self::hydrate(get_class(),
                             self::dbh()->fetch('* from mcz_Tune'));
    }

    public static function findOneByPath($path)
    {
        $res = self::hydrate(get_class(),
                             self::dbh()->fetch('* from ' . get_class() .
                                                ' where path=?', array($path)));
        if($res)
        {
            return $res[0];
        }
        return false;
    }

    public static function find($id)
    {
        $res = self::hydrate(get_class(),
                             self::dbh()->fetch('* from ' . get_class() .
                                                ' where id=?', array($id)));
        if($res)
        {
            return $res[0];
        }
        return false;
    }


    /**
     * Returns an array of Tunes. Caching is used.
     */
    public static function search($search, $offset = 0, $limit = 60,
                                  $metaphone = true)
    {
        $cacheId = 'search: "' . $search . '" [metaphone: '
                    . ($metaphone === true ? 'enabled' : 'disabled') . ']';
        $compare = 'key';
        if($metaphone)
        {
            $compare = 'sound';
        }
        if(!$res = mcz_Cache::_()->fetch($cacheId))
        {
            $conditions = array();
            $words = mcz_Analyzer::analyze($search);
            if(empty($words))
            {
                $res = array();
            }
            else
            {
                foreach($words as $word)
                {
                    $conditions[] = 'tune_id IN (SELECT tune_id FROM mcz_TuneIndex WHERE '
                                . $compare . ' = "' . ($metaphone ? metaphone($word) : $word) . '")';
                }
                $query = '
                COUNT(' . $compare . ') AS score, tune_id FROM mcz_TuneIndex
                WHERE ' . implode(' AND ', $conditions) . '
                GROUP BY tune_id ORDER BY score DESC';

                $res = mcz_Cache::_()->store($cacheId,
                                             self::dbh()->fetch($query),
                                             259200);
            }
        }

        $totalCount = count($res);
        $res = array_slice($res, $offset, $limit);
        $ids = array();
        foreach($res as $item)
        {
            $ids[] = $item['tune_id'];
        }

        if(!empty($ids))
        {
            $res = self::hydrate(get_class(),
                             self::dbh()->fetch('* from ' . get_class()
                                                . ' where id in('
                                                . implode(',', $ids) . ')'));
        }
        else
        {
            $res = array();
        }

        return array('total' => $totalCount, 'items' => $res);
    }
}